enum {
  LEFT_MOUSE_BUTTON = 0,
  RIGHT_MOUSE_BUTTON,
  NUM_MOUSE_BUTTONS
};

enum {
  GUI_BUTTON_START = 0,
  GUI_BUTTON_HIGH_SCORES,
  GUI_BUTTON_SOUND_IS_ON,
  GUI_BUTTON_SOUND_IS_OFF,
  GUI_BUTTON_INSTRUCTIONS,
  NUMBER_OF_GUI_BUTTONS
};

class Input {
  Button buttons_[NUMBER_OF_GUI_BUTTONS];
  
  int mouseX_;
  int mouseY_;

  bool pressed_[NUM_MOUSE_BUTTONS];
  

  Input() {

    for (int i = 0; i != NUM_MOUSE_BUTTONS; ++i) {
      pressed_[i] = false;
    }

    mouseX_ = 0;
    mouseY_ = 0;
  }

public:
  
  static Input &get()
  {
    static Input singleton;
    return singleton;
  }

  static int getX() {return get().mouseX_;}
  static int getY() {return get().mouseY_;}

  static bool isDown(int button) {
    return get().pressed_[button];
  }

  static void press(int button) {
    get().pressed_[button] = true;

    // press any visible button in range
    if (button == LEFT_MOUSE_BUTTON) {

      for (int i = 0; i != NUMBER_OF_GUI_BUTTONS; ++i) {
        if (get().buttons_[i].isVisible()) {
          if (isPointInsideButton(get().getX(), get().getY(), i)) {
            get().buttons_[i].setPressed(true);
          }
        }
      }
    }
  }

  static void release(int button) {
    get().pressed_[button] = false;

    // release any visible pressed button. if in range, engage!
    if (button == LEFT_MOUSE_BUTTON) {
      for (int i = 0; i != NUMBER_OF_GUI_BUTTONS; ++i) {
        if (get().buttons_[i].isVisible()) {
          if (isPointInsideButton(get().getX(), get().getY(), i)) {
            if (get().buttons_[i].isPressed()) {
              get().buttons_[i].setEngaged(true);
            }
          }
          if (get().buttons_[i].isPressed()) {
            get().buttons_[i].setPressed(false);
          }
        }
      }
    }
  }

  static void setMousePosition(int x, int y) {
    get().mouseX_ = x;
    get().mouseY_ = y;
  }

  static bool isPointInsideButton(int x, int y, int ref) {
    return get().buttons_[ref].isInside(x, y);
  }

  static Button getButton(int ref) {
    // Should make sure ref is within bounds first. To do...
    return get().buttons_[ref];
  }

  static void initButton(int ref, int image, int pressedImage, vec4 centre, vec4 halfExtents) {
    get().buttons_[ref].init(image, pressedImage, centre, halfExtents);
  }

  static void setButtonAsVisible(int ref, bool v) {get().buttons_[ref].setVisible(v);}

  static void drawVisibleButtons(shader &shader, texture* tex, mat4 modelToProjection) {
    for (int i = 0; i != NUMBER_OF_GUI_BUTTONS; ++i) {
      if (get().buttons_[i].isVisible()) {
        get().buttons_[i].draw(shader, tex, modelToProjection);
      }
    }
  }

  static bool isButtonEngaged(int ref) {return get().buttons_[ref].isEngaged();}
  static void disengageButton(int ref) {get().buttons_[ref].setEngaged(false);}
};

